home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / smaltalk.lha / smalltalk-1.1.1 / stix / mstcint.c < prev    next >
C/C++ Source or Header  |  1991-09-12  |  17KB  |  666 lines

  1. /***********************************************************************
  2.  *
  3.  *    C - Smalltalk Interface module
  4.  *
  5.  ***********************************************************************/
  6.  
  7. /***********************************************************************
  8.  *
  9.  * Copyright (C) 1990, 1991 Free Software Foundation, Inc.
  10.  * Written by Steve Byrne.
  11.  *
  12.  * This file is part of GNU Smalltalk.
  13.  *
  14.  * GNU Smalltalk is free software; you can redistribute it and/or modify it
  15.  * under the terms of the GNU General Public License as published by the Free
  16.  * Software Foundation; either version 1, or (at your option) any later 
  17.  * version.
  18.  * 
  19.  * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
  20.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
  21.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  22.  * more details.
  23.  * 
  24.  * You should have received a copy of the GNU General Public License along with
  25.  * GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
  26.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
  27.  *
  28.  ***********************************************************************/
  29.  
  30.  
  31. /*
  32.  *    Change Log
  33.  * ============================================================================
  34.  * Author      Date       Change 
  35.  * sbyrne     4 Jun 89      Added Smalltalk data conversion type.
  36.  *
  37.  * sbyrne    29 May 89      Created.
  38.  *
  39.  */
  40.  
  41. /* Define this to enable initialization of the SunView hacks in the
  42.    ./examples directory */
  43. /* #define SUN_WIN_HACKS */
  44.  
  45. #include "mst.h"
  46. #include "mstinterp.h"
  47. #include "mstdict.h"
  48. #include "mstoop.h"
  49. #include "mstsym.h"
  50.  
  51. #define ARG_VEC_SIZE        20 /* 20 ints, 10 longs or ptrs, 5 dbls */
  52.  
  53.  
  54. typedef enum {
  55.   intAlign,
  56.   longAlign,
  57.   ptrAlign,
  58.   doubleAlign
  59. } AlignmentType;
  60.  
  61. typedef enum {            /* types for C parameters */
  62.   unknownType,            /* when there is no type a priori */
  63.   charType,
  64.   stringType,
  65.   stringOutType,        /* for things that modify string params */
  66.   symbolType,
  67.   byteArrayType,
  68.   intType,
  69.   longType,
  70.   doubleType,
  71.   voidType,            /* valid only as a return type */
  72.   variadicType,            /* for parameters, this param is an array
  73.                    to be interpreted as arguments.  Note that
  74.                    only simple conversions are performed in
  75.                    this case. */
  76.   cObjectType,            /* a C object is being passed */
  77.   smalltalkType            /* no conversion to-from C...C sees this
  78.                    as "void *".  */
  79. } CDataType;
  80.  
  81. typedef struct CFuncDescriptorStruct {
  82.   OBJ_HEADER;
  83.   OOP        cFunction;
  84.   OOP        cFunctionName;
  85.   OOP        returnType;
  86.   OOP        numFixedArgs;
  87.   OOP        argTypes[1];    /* variable length, really numFixedArgs long */
  88. } *CFuncDescriptor;
  89.  
  90. typedef struct SymbolTypeMapStruct {
  91.   OOP        *symbol;
  92.   CDataType    type;
  93. } SymbolTypeMap;
  94.  
  95. typedef struct StringInfoStruct {
  96.   Byte        *cString;
  97.   OOP        stringOOP;
  98.   CDataType    returnedType;
  99. } StringInfo;
  100.  
  101. typedef union CParamUnionUnion {
  102.   int        intVal;
  103.   long        longVal;
  104.   voidPtr    ptrVal;
  105.   double    doubleVal;
  106.   int        valueVec[sizeof(double) / sizeof(int)];
  107. } CParamUnion;
  108.  
  109. typedef struct     CFuncInfoStruct {
  110.   char        *funcName;
  111.   void        (*funcAddr)();
  112. } CFuncInfo;
  113.  
  114. void                defineCFunc();
  115.  
  116. static void             pushObj(), callCFunction(),
  117.                 badType(), pushSmalltalkObj();
  118. static CDataType         getCType();
  119. static CFuncDescriptor         getCFuncDescriptor();
  120. static OOP            classifyTypeSymbol();
  121.  
  122. static CFuncInfo        cFuncInfo[100], *cFuncIndex = cFuncInfo;
  123. static int            cArgVec[ARG_VEC_SIZE];
  124. static int            *cArg;
  125. static StringInfo        stringInfo[ARG_VEC_SIZE], *sip;
  126. /* printable names for corresponding C types */
  127. static char            *cTypeName[] = {
  128.   "void?",            /* unknownType */
  129.   "char",            /* charType */
  130.   "char *",            /* stringType */
  131.   "char *",            /* stringType */
  132.   "char *",            /* symbolType */
  133.   "char *",            /* byteArrayType */
  134.   "int",            /* intType */
  135.   "long",            /* longType */
  136.   "double",            /* doubleType */
  137.   "void?",            /* voidType */
  138.   "var args?",            /* variadicType */
  139.   "void *",            /* cObjectType */
  140.   "void *",            /* smalltalkType */
  141. };
  142.  
  143. static SymbolTypeMap    symbolTypeMap[] = {
  144.   &unknownSymbol, unknownType,
  145.   &charSymbol, charType,
  146.   &stringSymbol, stringType,
  147.   &stringOutSymbol, stringOutType,
  148.   &symbolSymbol, symbolType,
  149.   &byteArraySymbol, byteArrayType,
  150.   &intSymbol, intType,
  151.   &longSymbol, longType,
  152.   &doubleSymbol, doubleType,
  153.   &voidSymbol, voidType,
  154.   &variadicSymbol, variadicType,
  155.   &cObjectSymbol, cObjectType,
  156.   &smalltalkSymbol, smalltalkType,
  157.   nil, unknownType
  158. };
  159.  
  160. /* the arg vec pointer must be = 0 mod alignments[align] */
  161. /* This is quite likely to be machine dependent.  Currently it is set up
  162.  * to work correctly on sun2's, sun3's and sun4's */
  163. static int         alignments[] = {
  164.   sizeof(int),            /* intType */
  165.   sizeof(long),            /* longType */
  166.   sizeof(voidPtr),        /* ptrType */
  167.   DOUBLE_ALIGNMENT        /* doubleType */
  168. };
  169.  
  170. static int        typeSizes[] = {
  171.   sizeof(int),            /* intType */
  172.   sizeof(long),            /* longType */
  173.   sizeof(voidPtr),        /* ptrType */
  174.   sizeof(double)        /* doubleType */
  175. };
  176.  
  177. /*
  178.  *    void marli(n)
  179.  *
  180.  * Description
  181.  *
  182.  *    Test/example C function.
  183.  *
  184.  * Inputs
  185.  *
  186.  *    n     : number of times to emit message.
  187.  *
  188.  */
  189. void marli(n)
  190. int n;
  191. {
  192.   int        i;
  193.  
  194.   for (i = 0; i < n; i++) {
  195.     printf("Marli loves Steve!!!\n");
  196.   }
  197. }
  198.  
  199. void initCFuncs()
  200. {
  201.   extern void marli(), windowLoop();
  202.   extern char *jeff(), *getAttrName();
  203.   extern voidPtr *getAttrValue();
  204.   extern void window_create();
  205.   extern int system();
  206.   extern char *getenv();
  207.   extern void defineSocket();
  208.  
  209.   defineSocket();
  210.   defineCFunc("system", system);
  211.   defineCFunc("getenv", getenv);
  212.   defineCFunc("marli", marli);
  213. #ifdef SUN_WIN_HACKS
  214.   defineWindowFuncs();
  215. #endif /* SUN_WIN_HACKS */
  216.  
  217. #ifdef notdefined
  218.   defineCFunc("jeff", jeff);
  219.   defineCFunc("getAttrName", getAttrName);
  220.   defineCFunc("getAttrValue", getAttrValue);
  221. #endif
  222. }
  223.  
  224. void defineCFunc(funcName, funcAddr)
  225. char    *funcName;
  226. void    (*funcAddr)();
  227. {
  228.   cFuncIndex->funcName = funcName;
  229.   cFuncIndex->funcAddr = funcAddr;
  230.   cFuncIndex++;
  231. }
  232.  
  233. void (*lookupFunction(funcName))()
  234. char    *funcName;
  235. {
  236.   CFuncInfo    *fip;
  237.  
  238.   for (fip = cFuncInfo; fip < cFuncIndex; fip++) {
  239.     if (strcmp(funcName, fip->funcName) == 0) {
  240.       return (fip->funcAddr);
  241.     }
  242.   }
  243.   return (nil);
  244. }
  245.  
  246.  
  247.  
  248. /*
  249.  *    void invokeCRoutine(numArgs, methodOOP)
  250.  *
  251.  * Description
  252.  *
  253.  *    Invokes a C routine.  The Smalltalk arguments have been popped off the
  254.  *    Smalltalk stack when this routine returns.
  255.  *
  256.  * Inputs
  257.  *
  258.  *    numArgs: 
  259.  *        
  260.  *    methodOOP: 
  261.  *        
  262.  *
  263.  */
  264. void invokeCRoutine(numArgs, methodOOP)
  265. long    numArgs;
  266. OOP    methodOOP;
  267. {
  268.   CFuncDescriptor desc;
  269.   CDataType    cType;
  270.   OOP        oop; /* oopArgVec[32]; */
  271.   Byte        *stringArg;
  272.   int        i;
  273.  
  274.   cArg = cArgVec;
  275.   
  276.   desc = getCFuncDescriptor(methodOOP);
  277.  
  278.   sip = stringInfo;
  279.  
  280.   for (i = 0; i < numArgs; i++) {
  281.     oop = stackAt(numArgs - i - 1);
  282.     cType = getCType(desc, i);
  283.     pushSmalltalkObj(oop, cType);
  284.   }
  285.  
  286.   popNOOPs(numArgs);
  287.  
  288.   callCFunction(desc);
  289.  
  290.   /* Fixup all returned string variables */
  291.   for ( ; sip-- != stringInfo; ) {
  292.     if (sip->returnedType == stringOutType) {
  293.       setOOPString(sip->stringOOP, sip->cString);
  294.     }
  295.     free(sip->cString);
  296.   }
  297. }
  298.  
  299. static CFuncDescriptor getCFuncDescriptor(methodOOP)
  300. OOP    methodOOP;
  301. {
  302.   OOP        associationOOP, descOOP;
  303.  
  304.   associationOOP = methodLiteralExt(methodOOP, 0);
  305.   descOOP = associationValue(associationOOP);
  306.   return ((CFuncDescriptor)oopToObj(descOOP));
  307. }
  308.  
  309. static CDataType getCType(desc, index)
  310. CFuncDescriptor desc;
  311. int    index;
  312. {
  313.   if (index < toInt(desc->numFixedArgs)) {
  314.     return ((CDataType)toInt(desc->argTypes[index]));
  315.   } else {
  316.     return (unknownType);
  317.   }
  318. }
  319.  
  320. static void pushSmalltalkObj(oop, cType)
  321. OOP    oop;
  322. CDataType cType;
  323. {
  324.   OOP        class;
  325.   int        i;
  326.   CParamUnion    u;
  327.  
  328.   if (cArg - cArgVec >= ARG_VEC_SIZE) {
  329.     errorf("Attempt to push more than %d ints; extra parameters ignored",
  330.        ARG_VEC_SIZE);
  331.     return;
  332.   }
  333.  
  334.   if (isInt(oop)) {
  335.     class = integerClass;
  336.   } else if (oop == trueOOP || oop == falseOOP) {
  337.     class = booleanClass;
  338.   } else {
  339.     class = oopClass(oop);
  340.   }
  341.  
  342.   if (cType == smalltalkType) {
  343.     u.ptrVal = (voidPtr)oop;
  344.     pushObj(&u, ptrAlign);
  345.   } else if (class == integerClass) {
  346.     if (cType == longType || cType == unknownType) {
  347.       u.longVal = toInt(oop);
  348.       pushObj(&u, longAlign);
  349.     } else if (cType == intType || cType == charType) {
  350.       u.intVal = toInt(oop);
  351.       pushObj(&u, intAlign);
  352.     } else {
  353.       badType("Integer", cType);
  354.     }
  355.   } else if (class == booleanClass) {
  356.     if (cType == intType || cType == charType || cType == unknownType) {
  357.       u.intVal = (oop == trueOOP);
  358.       pushObj(&u, intAlign);
  359.     } else if (cType == longType) {
  360.       u.longVal = (oop == trueOOP);
  361.       pushObj(&u, longAlign);
  362.     } else {
  363.       badType("Boolean", cType);
  364.     }
  365.   } else if (class == charClass) {
  366.     if (cType == charType || cType == unknownType) {
  367.       u.intVal = charOOPValue(oop);
  368.       pushObj(&u, intAlign);
  369.     } else {
  370.       badType("Character", cType);
  371.     }
  372.   } else if (class == stringClass) {
  373.     if (cType == stringType || cType == stringOutType
  374.     || cType == unknownType) {
  375.       if (sip - stringInfo >= ARG_VEC_SIZE) {
  376.     errorf("Too many string arguments, max is %d.  Extra ignored",
  377.            ARG_VEC_SIZE);
  378.       }
  379.       sip->cString = toCString(oop);
  380.       u.ptrVal = (voidPtr)sip->cString;
  381.       sip->stringOOP = oop;
  382.       sip->returnedType = cType;
  383.       sip++;
  384.       pushObj(&u, ptrAlign);
  385.     } else {
  386.       badType("String", cType);
  387.     }
  388.   } else if (class == symbolClass) {
  389.     if (cType == symbolType || cType == stringType || cType == unknownType) {
  390.       if (sip - stringInfo >= ARG_VEC_SIZE) {
  391.     errorf("Too many string arguments, max is %d.  Extra ignored",
  392.            ARG_VEC_SIZE);
  393.       }
  394.       sip->cString = toCString(oop);
  395.       u.ptrVal = (voidPtr)sip->cString;
  396.       sip->stringOOP = oop;
  397.       sip->returnedType = cType;
  398.       sip++;
  399.       pushObj(&u, ptrAlign);
  400.     } else {
  401.       badType("Symbol", cType);
  402.     }
  403.   } else if (class == byteArrayClass) {
  404.     if (cType == byteArrayType || cType == unknownType) {
  405.       if (sip - stringInfo >= ARG_VEC_SIZE) {
  406.     errorf("Too many string arguments, max is %d.  Extra ignored",
  407.            ARG_VEC_SIZE);
  408.       }
  409.       sip->cString = toByteArray(oop);
  410.       u.ptrVal = (voidPtr)sip->cString;
  411.       sip->stringOOP = oop;
  412.       sip->returnedType = cType;
  413.       sip++;
  414.       pushObj(&u, ptrAlign);
  415.     } else {
  416.       badType("ByteArray", cType);
  417.     }
  418.   } else if (class == floatClass) {
  419.     if (cType == doubleType || cType == unknownType) {
  420.       u.doubleVal = floatOOPValue(oop);
  421.       pushObj(&u, doubleAlign);
  422.     } else {
  423.       badType("Float", cType);
  424.     }
  425.   } else if (class == cObjectClass) { 
  426.     if (cType == cObjectType || cType == unknownType) {
  427.       u.ptrVal = cObjectValue(oop);
  428.       pushObj(&u, ptrAlign);
  429.     } else {
  430.       badType("CObject", cType);
  431.     }
  432.   } else if (class == undefinedObjectClass) {
  433.     switch (cType) {
  434.     case cObjectType:
  435.     case stringType:
  436.     case symbolType:
  437.     case unknownType:
  438.       u.ptrVal = nil;
  439.       pushObj(&u, ptrAlign);
  440.       break;
  441.  
  442.     default:
  443.       badType("UndefinedObject", cType);
  444.     }
  445.   } else if (class == arrayClass) {
  446.     for (i = 1; i <= numOOPs(oopToObj(oop)); i++) {
  447.       pushSmalltalkObj(arrayAt(oop, i), unknownType);
  448.     }
  449.   }
  450.   
  451. }
  452.  
  453. static void pushObj(up, align)
  454. CParamUnion *up;
  455. AlignmentType align;
  456. {
  457.   int i, alignInts;
  458.  
  459.   alignInts = alignments[ENUM_INT(align)] / sizeof(int);
  460.  
  461.   /* Align the stack properly */
  462.   if ((cArg - cArgVec) % alignInts) {
  463.     cArg += alignInts - ((cArg - cArgVec) % alignInts);
  464.   }
  465.   
  466.   for (i = 0; i < typeSizes[ENUM_INT(align)] / sizeof(int); i++) {
  467.     if (cArg - cArgVec >= ARG_VEC_SIZE) {
  468.       errorf("Too many parameters, max = %d.  Extra parameters ignored",
  469.          ARG_VEC_SIZE);
  470.       return;
  471.     }
  472.     *cArg++ = up->valueVec[i];
  473.   }
  474. }
  475.  
  476. static void callCFunction(desc)
  477. CFuncDescriptor desc;
  478. {  
  479.   int        intResult;
  480.   long        longResult;
  481.   double    doubleResult;
  482.   int        (*cFunction)();
  483.   CDataType    returnType;
  484.  
  485.   cFunction = (int (*)())cObjectValue(desc->cFunction);
  486.   returnType = (CDataType)toInt(desc->returnType);
  487.  
  488.   switch (returnType) {
  489.   case voidType:
  490.     (*cFunction)(
  491.       cArgVec[0],  cArgVec[1],  cArgVec[2],  cArgVec[3],
  492.       cArgVec[4],  cArgVec[5],  cArgVec[6],  cArgVec[7],
  493.       cArgVec[8],  cArgVec[9],  cArgVec[10], cArgVec[11],
  494.       cArgVec[12], cArgVec[13], cArgVec[14], cArgVec[15],
  495.       cArgVec[16], cArgVec[17], cArgVec[18], cArgVec[19]);
  496.     break;
  497.   case charType:
  498.   case intType:
  499.     intResult = (*cFunction)(
  500.       cArgVec[0],  cArgVec[1],  cArgVec[2],  cArgVec[3],
  501.       cArgVec[4],  cArgVec[5],  cArgVec[6],  cArgVec[7],
  502.       cArgVec[8],  cArgVec[9],  cArgVec[10], cArgVec[11],
  503.       cArgVec[12], cArgVec[13], cArgVec[14], cArgVec[15],
  504.       cArgVec[16], cArgVec[17], cArgVec[18], cArgVec[19]);
  505.     switch (returnType) {
  506.     case intType: 
  507.       setStackTop(fromInt((long)intResult));
  508.       break;
  509.     case charType:
  510.       setStackTop(charOOPAt((Byte)intResult));
  511.       break;
  512.     }
  513.     break;
  514.  
  515.   case longType:
  516.   case stringType:
  517.   case symbolType:
  518.   case cObjectType:
  519.   case smalltalkType:
  520.     longResult = (*(long (*)())cFunction)(
  521.       cArgVec[0],  cArgVec[1],  cArgVec[2],  cArgVec[3],
  522.       cArgVec[4],  cArgVec[5],  cArgVec[6],  cArgVec[7],
  523.       cArgVec[8],  cArgVec[9],  cArgVec[10], cArgVec[11],
  524.       cArgVec[12], cArgVec[13], cArgVec[14], cArgVec[15],
  525.       cArgVec[16], cArgVec[17], cArgVec[18], cArgVec[19]);
  526.     switch (returnType) {
  527.     case longType:
  528.       setStackTop(fromInt(longResult));
  529.       break;
  530.     case stringType:
  531.       if (longResult == 0) {
  532.     setStackTop(nilOOP);
  533.       } else {
  534.     setStackTop(stringNew((char *)longResult));
  535.       }
  536.       break;
  537.     case symbolType:
  538.       if (longResult == 0) {
  539.     setStackTop(nilOOP);
  540.       } else {
  541.     setStackTop(internString((char *)longResult));
  542.       }
  543.       break;
  544.     case cObjectType:
  545.       if (longResult == 0) {
  546.     setStackTop(nilOOP);
  547.       } else {
  548.     setStackTop(cObjectNew((voidPtr)longResult));
  549.       }
  550.       break;
  551.     case smalltalkType:
  552.       setStackTop((OOP)longResult);
  553.       break;
  554.     }
  555.     break;
  556.  
  557.   case doubleType:
  558.     doubleResult = (*(double (*)())cFunction)(
  559.       cArgVec[0],  cArgVec[1],  cArgVec[2],  cArgVec[3],
  560.       cArgVec[4],  cArgVec[5],  cArgVec[6],  cArgVec[7],
  561.       cArgVec[8],  cArgVec[9],  cArgVec[10], cArgVec[11],
  562.       cArgVec[12], cArgVec[13], cArgVec[14], cArgVec[15],
  563.       cArgVec[16], cArgVec[17], cArgVec[18], cArgVec[19]);
  564.     setStackTop(floatNew(doubleResult));
  565.     break;
  566.  
  567.   default:
  568.     errorf("Invalid C function return type specified, index %d\n",
  569.        returnType);
  570.     break;
  571.   }
  572.  
  573. }
  574.  
  575. static void badType(smalltalkTypeName, cType)
  576. char    *smalltalkTypeName;
  577. CDataType cType;
  578. {
  579.   errorf("Attempt to pass a %s as a %s", smalltalkTypeName,
  580.      cTypeName[ENUM_INT(cType)]);
  581. }
  582.  
  583.  
  584. OOP makeDescriptor(funcNameOOP, returnTypeOOP, argsOOP)
  585. OOP    funcNameOOP, returnTypeOOP, argsOOP;
  586. {
  587.   char        *funcName;
  588.   void        (*funcAddr)();
  589.   int        numArgs, i;
  590.   CFuncDescriptor desc;
  591.  
  592.   funcName = (char *)toCString(funcNameOOP);
  593.   funcAddr = lookupFunction(funcName);
  594.  
  595.   if (argsOOP == nilOOP) {
  596.     numArgs = 0;
  597.   } else {
  598.     numArgs = numOOPs(oopToObj(argsOOP));
  599.   }
  600.  
  601.   /*
  602.    * since these are all either ints or new objects, I'm not moving the
  603.    * oops
  604.    */
  605.   desc = (CFuncDescriptor)newInstanceWith(cFuncDescriptorClass, numArgs);
  606.   desc->cFunction = cObjectNew(funcAddr);
  607.   desc->cFunctionName = stringNew(funcName);
  608.   desc->numFixedArgs = fromInt(numArgs);
  609.   desc->returnType = classifyTypeSymbol(returnTypeOOP);
  610.   for (i = 1; i <= numArgs; i++) {
  611.     desc->argTypes[i - 1] = classifyTypeSymbol(arrayAt(argsOOP, i));
  612.   }
  613.  
  614.   return (allocOOP(desc));
  615. }
  616.  
  617. static OOP classifyTypeSymbol(symbolOOP)
  618. OOP    symbolOOP;
  619. {
  620.   SymbolTypeMap    *sp;
  621.   Byte        *symbolName;
  622.  
  623.   for (sp = symbolTypeMap; sp->symbol != nil; sp++) {
  624.     if (*sp->symbol == symbolOOP) {
  625.       return (fromInt(sp->type));
  626.     }
  627.   }
  628.  
  629.   symbolName = toCString(symbolOOP); /* yeah yeah...but they have the same
  630.                         representation! */
  631.   errorf("Unknown data type symbol: %s", symbolName);
  632.  
  633.   return (fromInt(unknownType));
  634. }
  635.  
  636. /*
  637.  *    void restoreCFuncDescriptor(cFuncDescOOP)
  638.  *
  639.  * Description
  640.  *
  641.  *    This routine is called during image loading to restore a C function
  642.  *    descriptor pointer.  This is because between the time that the image
  643.  *    was made and now, the executable image may have changed, so any
  644.  *    reference to the C function address may be invalid.  We therefore just
  645.  *    perform the function lookup again and use that value.
  646.  *
  647.  * Inputs
  648.  *
  649.  *    cFuncDescOOP: 
  650.  *        A C function descriptor object to be adjusted.  Contains the
  651.  *        name of the function to be looked up.
  652.  *
  653.  */
  654. void restoreCFuncDescriptor(cFuncDescOOP)
  655. OOP    cFuncDescOOP;
  656. {
  657.   CFuncDescriptor desc;
  658.   void        (*funcAddr)();
  659.   char        *funcName;
  660.  
  661.   desc = (CFuncDescriptor)oopToObj(cFuncDescOOP);
  662.   funcName = (char *)toCString(desc->cFunctionName);
  663.   funcAddr = lookupFunction(funcName);
  664.   setCObjectValue(desc->cFunction, funcAddr);
  665. }
  666.